/*
 * Copyright 2002-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.aop.framework;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.aop.Advisor;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.Nullable;

/**
 * Base class for {@link BeanPostProcessor} implementations that apply a
 * Spring AOP {@link Advisor} to specific beans.
 *
 * @author Juergen Hoeller
 * @since 3.2
 * 它继承自，ProxyProcessorSupport，说明它也拥有Aop的通用配置
 * 此类处理Advisor和Bean的关系的
 */
@SuppressWarnings("serial")
public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSupport implements BeanPostProcessor {

	@Nullable
	protected Advisor advisor;

	protected boolean beforeExistingAdvisors = false;

	// 缓存合格的Bean们
	private final Map<Class<?>, Boolean> eligibleBeans = new ConcurrentHashMap<>(256);


	/**
	 * 当遇到一个pre-object的时候，是否把该processor所持有得advisor放在现有的增强器们之前执行
	 *  默认是false，会放在最后一个位置上的
	 */
	public void setBeforeExistingAdvisors(boolean beforeExistingAdvisors) {
		this.beforeExistingAdvisors = beforeExistingAdvisors;
	}


	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
		return bean;
	}


	/**
	 * 初始化之后，进行代理逻辑处理
	 */
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		// 1、如果不存在advisor，或者这个bean是SpringAOP基础组件，不进行代理处理
		if (this.advisor == null || bean instanceof AopInfrastructureBean) {
			return bean;
		}

		//2 如果这个Bean已经被代理过了（比如已经被AOP切中了），那本处就无需再重复创建代理了，直接向里面添加advisor就成了
		if (bean instanceof Advised) {
			Advised advised = (Advised) bean;
			// 注意此advised不能是已经被冻结了的。且源对象必须是Eligible合格的
			if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
				if (this.beforeExistingAdvisors) {
					advised.addAdvisor(0, this.advisor);
				}
				else {
					advised.addAdvisor(this.advisor);
				}
				return bean;
			}
		}
		//3 如果这个bean还没有被代理过的,且Bean符合被代理条件，执行代理逻辑
		if (isEligible(bean, beanName)) {
			ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);

			// 如果是JDK代理，那就去分析出它所实现的接口们  然后放进ProxyFactory 里去
			if (!proxyFactory.isProxyTargetClass()) {
				evaluateProxyInterfaces(bean.getClass(), proxyFactory);
			}
			// 切面就是当前持有得advisor
			proxyFactory.addAdvisor(this.advisor);
			// 模板方法
			customizeProxyFactory(proxyFactory);

			// 最终返回这个代理对象
			return proxyFactory.getProxy(getProxyClassLoader());
		}

		// No proxy needed.
		return bean;
	}

	/**
	 * 判断这个bean是否应该被创建代理对象
	 */
	protected boolean isEligible(Object bean, String beanName) {
		return isEligible(bean.getClass());
	}

	/**
	 * 判断这个类是否应该被创建代理对象
	 */
	protected boolean isEligible(Class<?> targetClass) {
		//1 如果已经被缓存着了，那肯定靠谱啊
		Boolean eligible = this.eligibleBeans.get(targetClass);
		if (eligible != null) {
			return eligible;
		}
		//2 如果没有切面（就相当于没有给配置增强器，那铁定是不合格的）
		if (this.advisor == null) {
			return false;
		}
		//3 核心方法，判断这个advisor是否能够切入进targetClass这个类，能够切入进取的也是合格的
		eligible = AopUtils.canApply(this.advisor, targetClass);
		this.eligibleBeans.put(targetClass, eligible);
		return eligible;
	}

	/**
	 * 准备代理工厂
	 */
	protected ProxyFactory prepareProxyFactory(Object bean, String beanName) {
		ProxyFactory proxyFactory = new ProxyFactory();
		// 将自身的属性，赋值给代理工厂
		proxyFactory.copyFrom(this);
		proxyFactory.setTarget(bean);
		return proxyFactory;
	}

	/**
	 * 模板方法：提供给子类补充代理工厂
	 */
	protected void customizeProxyFactory(ProxyFactory proxyFactory) {
	}

}
